using System;
using System.Collections.Generic;

public class PermutMapper : GenMapper<string>
{
	public PermutMapper (){
  	  Console.WriteLine("---- new PermutMapper ----");
	  strategies.Add(new Swap0NStrategy());
	}
	
	static string elements = "abcdefghijklmnopqrstuvwxyz";
	static int charIdx(char c){
		return c - 'a';
	}
	void assertPermutFrom(string test){
		string sub = elements.Substring(0,test.Length);
		if( !test.Equals(sub) ){
				throw new Exception("(1) not permut from: "+test);
		}
	}

	void assertPermut(string test){
		string sub = elements.Substring(0,test.Length);
		for( int i=0; i<test.Length; i++ ){
			char c = test[i];
			if( ! sub.Contains(""+c) ){
				throw new Exception("(1) not permut: "+test);
			}
		}
		for( int i=0; i<sub.Length; i++ ){
			char c = sub[i];
			if( ! test.Contains(""+c) ){
				throw new Exception("(2) not permut: "+test);
			}
		}
	}
	
	protected override void ruleCompose (Rule<string> newRule)
	{
		Console.WriteLine("skipping rule, compose not implemented "+newRule);
		//throw new NotImplementedException ();
	}
	
	public override void addMapping(string from, string to){
		assertPermutFrom(from);
		assertPermut(to);
		if( from.Length != to.Length ){
			throw new Exception("not permut: "+from+", "+to);
		}
		base.addMapping(from, to);
	}
	
	public override string map (string from)
	{
		assertPermutFrom(from);
		return base.map (from);
	}
	
	class Swap0NRule : Rule<string>{
		IntMapper n;
		public Swap0NRule (IntMapper n)
		{
			this.n = n;
		}
		
		public override void addCorrectiveMapping(string from, string to){
			int ni = swap0NSuggest(to);
			if( ni>0 ){
				// this is a simple swap of 0 to N, our responsibility zone,
				// we need to accomodate it if we can, no other strategy class is going to do it
				Console.WriteLine("permut addCorrectiveMapping int mapping "+from.Length+" to "+ ni);
				n.addMapping(from.Length, ni);
			}else{
				// not a simple swap, we can't accomodate this
			}

		}

		public override string map (string from){
			int nPos = n.map(from.Length);
			Console.WriteLine("permut int map query "+from.Length+" ret="+nPos);
			if( nPos >= from.Length ){
				Console.WriteLine("map for "+from+" can't swap 0 with " + nPos );
				return from;
			}
			
			string ret = "";
			for( int i=0; i<from.Length; i++ ){
				int j = i;
				if( i==0 ) j=nPos;
				if( i==nPos ) j=0;
				ret += from[j];
			}
			return ret;
		}
		public override string ToString ()
		{
			return string.Format ("[Swap0NRule n={0}]",n.ToString());
		}
	}
	
	static	int swap0NSuggest(string to){
			int idxAt0 = charIdx(to[0]);
			if( idxAt0>0 ){
				if( 'a'==to[idxAt0] ){
					return idxAt0;
				}
			}
			return -1;
		}

	class Swap0NStrategy : Strategy<string>{
		
		public override Rule<string> toRule(IList<Pair<string>> pairs){
			Console.WriteLine("PermutMapper toRule pairs size " + pairs.Count);
			IntMapper intMapper = new IntMapper();
			bool swaps=false;
			foreach( Pair<string> p in pairs ){
				int n = swap0NSuggest(p.to);
				if( n>0 ){
					Console.WriteLine("permut added int mapping "+p.from.Length+" to "+ n);
					intMapper.addMapping(p.from.Length, n);
					swaps=true;
				}
			}
			if( swaps ){
					return new Swap0NRule(intMapper);
			}
			return null;
		}
	}

}

 